package com.hbx.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hbx.auth.AuthCacheService;
import com.hbx.constant.CachePrefixContent;
import com.hbx.dto.blog.InsertDto;
import com.hbx.dto.blog.SearchBlogDto;
import com.hbx.mapper.RankMapper;
import com.hbx.model.Blog;
import com.hbx.mapper.BlogMapper;
import com.hbx.model.Comment;
import com.hbx.model.Rank;
import com.hbx.model.User;
import com.hbx.service.BlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbx.service.CommentService;
import com.hbx.service.UserService;
import com.hbx.utils.CacheUtils;
import com.hbx.utils.Result;
import com.hbx.vo.PageBean;
import com.hbx.vo.RankVo;
import com.hbx.vo.blog.BlogCommentVo;
import com.hbx.vo.blog.BlogVo;
import com.hbx.vo.blog.MyBlogVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hbx
 * @since 2022-01-15
 */
@Service
@Slf4j
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements BlogService {

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private CommentService commentService;

    @Autowired
    private UserService userService;

    @Autowired
    private RankMapper rankMapper;

    @Autowired
    private CacheUtils cacheUtils;
    /**
     * 查询我的博客
     * @param pageSize
     * @param userId
     * @param r
     */
    @Override
    public void getMyBlog(Integer pageSize, Integer userId, Result r) {
        // 查询博客
        User user = userService.getById(userId);
        List<MyBlogVo> voList = new ArrayList<>();
        if (user == null){
            log.error("【系统提示】:用户信息不存在");
            r.setCode(201).setMsg("用户信息不存在");
            return;
        }
        Page<Blog> page = new Page(0, pageSize);
        QueryWrapper<Blog> wrapper = new QueryWrapper();
        wrapper.eq("blog_userid",user.getUserId());
        wrapper.orderByDesc("blog_push_time");
        wrapper.eq("blog_is_deleted",0);

        IPage<Blog> blogIPage = blogMapper.selectPage(page, wrapper);

        List<Blog> blogList = blogIPage.getRecords();

        blogList.stream().forEach(blog -> {
            MyBlogVo myBlogVo = new MyBlogVo();
            BeanUtils.copyProperties(blog,myBlogVo);
            if (blog.getBlogLable() != null){
                String[] split = blog.getBlogLable().split(",");
                if (!ObjectUtils.isEmpty(split)){
                    myBlogVo.setBlogLableList(Arrays.asList(split));
                }
            }
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("blog_id",blog.getBlogId());
            myBlogVo.setCommentNum(commentService.count(queryWrapper));
            voList.add(myBlogVo);
        });
        r.setCode(200).setData(voList);
    }

    /**
     * 查询所有博客分页
     * @param search
     * @param r
     */
    @Override
    public void getBlogListPage(SearchBlogDto search, Result r) {
        Integer pageNum = search.getPageNum();
        Integer pageSize = search.getPageSize();
        String keyword = search.getKeyword();
        PageBean pageBean = new PageBean<>();
        User currentUser = AuthCacheService.getUser();
        Page<Blog> page = new Page<>(pageNum,pageSize);
        QueryWrapper<Blog> wrapper = new QueryWrapper<>();
        wrapper.eq("blog_is_deleted",0)
                .orderByDesc("blog_push_time");
        if (StringUtils.hasLength(keyword)){
            wrapper.like("blog_content",keyword)
                    .or().like("blog_title",keyword)
                    .or().like("blog_lable",keyword);
        }
        IPage<Blog> blogIPage = blogMapper.selectPage(page, wrapper);
        pageBean.setPageNum(blogIPage.getCurrent());
        pageBean.setTotal(blogIPage.getTotal());
        pageBean.setPageSize(blogIPage.getSize());
        List<Blog> records = blogIPage.getRecords();
        // 没有数据
        if (CollectionUtils.isEmpty(records)){
            r.setCode(200).setData(pageBean);
            return;
        }
        List<BlogVo> list = new ArrayList<>();
        records.stream().forEach(record -> {
            BlogVo vo = new BlogVo();
            BeanUtils.copyProperties(record, vo);
            Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_BLOG_NIU + record.getBlogId());
            if (!CollectionUtils.isEmpty(members) && members.contains(currentUser.getUserId())){
                vo.setIsNiu(1);
            }
            // 设置用户
            BlogVo.UserVo userVo = new BlogVo.UserVo();
            User user = userService.getById(record.getBlogUserid());
            if (ObjectUtils.isEmpty(user)){
                return;
            }
            // 设置系统头衔
            List<Rank> rankList = rankMapper.selectListByUserId(user.getUserId());
            if (!CollectionUtils.isEmpty(rankList)){
                List<RankVo> voList = new ArrayList<>();
                rankList.stream().forEach(rank -> {
                    RankVo rankVo = new RankVo();
                    BeanUtils.copyProperties(rank, rankVo);
                    voList.add(rankVo);
                });
                userVo.setRankList(voList);
            }
            userVo.setUserId(user.getUserId());
            userVo.setUserName(user.getLoginName());
            userVo.setAvatar(user.getAvator());
            vo.setUser(userVo);
            // 设置标签
            String blogLable = record.getBlogLable();
            if (StringUtils.hasLength(blogLable)){
                vo.setBlogTags(Arrays.asList(blogLable.split(",")));
            }
            // 查询评论
            QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("blog_id",record.getBlogId())
                    .isNull("parent_comment_id");
            int count = commentService.count(queryWrapper);
            vo.setCommentCount(count);
            list.add(vo);
        });
        pageBean.setData(list);
        r.setCode(200).setData(pageBean).setMsg("操作成功");
    }

    /**
     * 点赞或取消
     * @param blogId
     * @param r
     */
    @Override
    public void addNiu(Integer blogId, Result r) {
        User user = AuthCacheService.getUser();
        Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_BLOG_NIU + blogId);
        if (members.contains(user.getUserId())){
            // 取消点赞
            if (blogMapper.niu("decrement", blogId) == 1){
                Long remove = cacheUtils.setRemove(CachePrefixContent.PLAT_BLOG_NIU + blogId, new Object[]{user.getUserId()});
                if (remove > 0){
                    r.setCode(200).setData(0);
                    return;
                }
            }
            r.setData(201).setMsg("操作失败");
        }else {
            if (blogMapper.niu("increment", blogId) == 1){
                Long remove = cacheUtils.add(CachePrefixContent.PLAT_BLOG_NIU + blogId, new Object[]{user.getUserId()});
                if (remove > 0){
                    r.setCode(200).setData(1);
                    return;
                }
            }
            r.setData(201).setMsg("操作失败");
        }
    }

    /**
     * 添加博客
     * @param dto
     * @param r
     */
    @Override
    public void insertBlog(InsertDto dto, Result r) {
        User user = AuthCacheService.getUser();
        Blog blog = new Blog();
        BeanUtils.copyProperties(dto, blog);
        List<String> blogImages = dto.getBlogImages();
        List<String> blogTagList = dto.getBlogTagList();
        if (!CollectionUtils.isEmpty(blogImages)){
            StringJoiner joiner = new StringJoiner(",");
            blogImages.stream().forEach(img -> {
                joiner.add(img);
            });
            blog.setBlogImg(joiner.toString());
        }
        if (!CollectionUtils.isEmpty(blogTagList)){
            StringJoiner joiner = new StringJoiner(",");
            blogTagList.stream().forEach(tag -> {
                joiner.add(tag);
            });
            blog.setBlogLable(joiner.toString());
        }
        blog.setBlogPushTime(new Date());
        blog.setBlogUserid(user.getUserId());
        int insert = blogMapper.insert(blog);
        if (insert != 1){
            r.setCode(201).setMsg("博客添加失败");
            return;
        }
        r.setCode(200).setMsg("添加成功");
    }

    /**
     * 用户删除博客
     * @param blogId
     * @param r
     */
    @Override
    public void removeBlog(Integer blogId, Result r) {
        User user = AuthCacheService.getUser();
        Blog blog = blogMapper.selectById(blogId);
        if (blog == null){
            r.setCode(201).setMsg("博客不存在,请重新加载页面");
            return;
        }
        if (!user.getUserId().equals(blog.getBlogUserid())){
            r.setCode(201).setMsg("非法操作,删除失败");
            return;
        }
        int result = blogMapper.deleteById(blog);
        if (result == 1){
            r.setCode(200).setMsg("博客删除成功");
            return;
        }
        r.setCode(201).setMsg("删除失败");
    }

    @Override
    public void getBlogDetail(Integer blogId, Result r) {
        User currentUser = AuthCacheService.getUser();
        Blog blog = blogMapper.selectById(blogId);
        if (blog == null || blog.getBlogIsDeleted() == 1){
            r.setCode(201).setMsg("博客不存在");
            return;
        }
        BlogVo vo = new BlogVo();
        BeanUtils.copyProperties(blog, vo);
        Set<Object> members = cacheUtils.getSetMembers(CachePrefixContent.PLAT_BLOG_NIU + blog.getBlogId());
        if (!CollectionUtils.isEmpty(members) && members.contains(currentUser.getUserId())){
            vo.setIsNiu(1);
        }
        // 设置用户
        BlogVo.UserVo userVo = new BlogVo.UserVo();
        User user = userService.getById(blog.getBlogUserid());
        if (ObjectUtils.isEmpty(user)){
            r.setCode(201).setMsg("博客不存在");
            return;
        }
        // 设置系统头衔
        List<Rank> rankList = rankMapper.selectListByUserId(user.getUserId());
        if (!CollectionUtils.isEmpty(rankList)){
            List<RankVo> voList = new ArrayList<>();
            rankList.stream().forEach(rank -> {
                RankVo rankVo = new RankVo();
                BeanUtils.copyProperties(rank, rankVo);
                voList.add(rankVo);
            });
            userVo.setRankList(voList);
        }
        userVo.setUserId(user.getUserId());
        userVo.setUserName(user.getLoginName());
        userVo.setAvatar(user.getAvator());
        vo.setUser(userVo);
        // 设置标签
        String blogLable = blog.getBlogLable();
        if (StringUtils.hasLength(blogLable)){
            vo.setBlogTags(Arrays.asList(blogLable.split(",")));
        }
        // 查询评论
        QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("blog_id",blog.getBlogId())
                .isNull("parent_comment_id")
                .orderByDesc("comment_date");
        List<Comment> comments = commentService.list(queryWrapper);
        if (CollectionUtils.isEmpty(comments)){
            vo.setCommentList(new ArrayList<>());
        } else {
            // 处理评论
            List<BlogCommentVo> commentVoList = new ArrayList<>();
            comments.stream().forEach(comment -> {
                BlogCommentVo commentVo = new BlogCommentVo();
                BeanUtils.copyProperties(comment, commentVo);
                User commentUser = userService.getById(comment.getCommentWid());
                if (commentUser == null){
                    return;
                }
                BlogCommentVo.CommentUser u = new BlogCommentVo.CommentUser();
                u.setUserId(commentUser.getUserId());
                u.setUserName(commentUser.getLoginName());
                u.setAvator(commentUser.getAvator());
                commentVo.setWuser(u);
                if (comment.getParentCommentId() != null){
                    User parentUser = userService.getById(comment.getParentCommentId());
                    if (parentUser != null){
                        BlogCommentVo.CommentUser pu = new BlogCommentVo.CommentUser();
                        pu.setUserId(commentUser.getUserId());
                        pu.setUserName(commentUser.getLoginName());
                        pu.setAvator(commentUser.getAvator());
                        commentVo.setParentCommentUser(pu);
                    }
                }
                recursionSetChildren(commentVo, comment.getCommentId());
                commentVoList.add(commentVo);
            });
            vo.setCommentList(commentVoList);
        }
        r.setCode(200).setData(vo).setMsg("操作成功");
    }

    /**
     * 递归多级评论
     * @param commentVo
     * @param commentId
     */
    private void recursionSetChildren(BlogCommentVo commentVo, Integer commentId) {
        if (commentId == null){
            return;
        }
        QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_comment_id",commentId);
        List<Comment> comments = commentService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(comments)){
            comments.stream().forEach(comm -> {
                BlogCommentVo vo = new BlogCommentVo();
                BeanUtils.copyProperties(comm, vo);
                User commentUser = userService.getById(comm.getCommentWid());
                if (commentUser == null){
                    return;
                }
                BlogCommentVo.CommentUser u = new BlogCommentVo.CommentUser();
                u.setUserId(commentUser.getUserId());
                u.setUserName(commentUser.getLoginName());
                u.setAvator(commentUser.getAvator());
                vo.setWuser(u);
                if (comm.getParentCommentId() != null){
                    User parentUser = userService.getById(comm.getParentCommentId());
                    if (parentUser != null){
                        BlogCommentVo.CommentUser pu = new BlogCommentVo.CommentUser();
                        pu.setUserId(commentUser.getUserId());
                        pu.setUserName(commentUser.getLoginName());
                        pu.setAvator(commentUser.getAvator());
                        vo.setParentCommentUser(pu);
                    }
                }
                commentVo.getChildren().add(vo);
                recursionSetChildren(vo, comm.getCommentId());
            });
        }
    }

}
